package com.reg;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class RegEx {

    SequenceRegular sequenceRegular;
    public RegEx(String reg){

        ArrayList<SequenceRegular> regulars = createRegular(reg);
        if(regulars==null || regulars.size()==0) throw new RuntimeException("formar error");
        else if(regulars.size() > 1)throw new RuntimeException(", error");
        else {
            sequenceRegular = regulars.get(0);
        }
    }

    public List<String> match(String inputString){
        return match(inputString.toCharArray());
    }

    private List<String> match(char[] chars){
        List<String> re = new ArrayList<String>();
        for(int i = 0;i < chars.length  ;i ++){
            List<String> matchedStrings = sequenceRegular.match(Arrays.copyOfRange(chars,i,chars.length));
            if(null!=matchedStrings) {
                re.addAll(matchedStrings);
            }
        }
        return re;
    }

    ArrayList<SequenceRegular> createRegular(String reg){

        ArrayList<SequenceRegular> regulars = new ArrayList<>();
        IRegular regular = null;
        SequenceRegular sequenceRegular = new SequenceRegular();
        if(!reg.isEmpty()){
            int begin = 0;
            for(int i = 0 ;i < reg.length();){
                char c = reg.charAt(0);
                switch (c){
                    case '[': {
                        if(regular!=null){
                            sequenceRegular.addRegular(regular);
                        }
                        int j = pair(reg, i);
                        String sb = reg.substring(i + 1, j);
                        ArrayList<SequenceRegular> bracket = createRegular(sb);
                        i = j+1;
                        regular = new BracketRegular(bracket);
                        begin = i;
                    }break;
                    case '(': {
                        if(regular!=null){
                            sequenceRegular.addRegular(regular);
                        }
                        int j = pair(reg, i);
                        String sb = reg.substring(i + 1, j);
                        ArrayList<SequenceRegular> bracket = createRegular(sb);
                        i = j+1;
                        if(bracket.size()!=1)throw new RuntimeException("() format error.");
                        regular = bracket.get(0);
                        begin = i;
                    }break;
                    case ',': {
                        i++;
                        if(sequenceRegular.getSequenceCount()==0)throw new RuntimeException(", error");
                        regulars.add(sequenceRegular);
                    }break;
                    case '+': {
                        if(i>begin)regular = new CharSequenceRegular(reg.substring(begin, i));
                        i++;
                        if(regular != null){
                            regular = new PlusRegular(regular);
                            begin = i;
                        }
                        else throw new RuntimeException("+ format error");
                    }break;
                    case '*':
                        if(i>begin)regular = new CharSequenceRegular(reg.substring(begin, i));
                        i++;
                        if(regular != null){
                            regular = new AsteriskRegular(regular);
                            begin = i;
                        }
                        else throw new RuntimeException("* format error");
                        break;
                    default:
                        if(regular!=null){
                            sequenceRegular.addRegular(regular);
                            regular = null;
                        }
                        i++;
                        break;
                }
            }


        }
        return regulars;
    }

    private int pair(String s,int i){
        int pairCount = 0;
        char c = s.charAt(i);
        char cp = ']';
        if('{'==s.charAt(i)) {
            cp = '}';
        }
        for(;i<s.length();i++){
            if(c == s.charAt(i))pairCount++;
            else if(cp == s.charAt(i)){
                pairCount--;
                if(pairCount==0)return i;
            }
        }
        throw new RuntimeException("char "+ c +" is not paired.");
    }
}
